﻿ 
#include "stdafx.h"
#include "Category.h"
#include "export_functions.h"



//======================================================================
//					CategoryReiting							
//======================================================================

void CategoryReiting_e::to_cstr(char* dest) const
{

	switch(value)
	{
	case very_height: { strcpy(dest,"very_height"); } break;
	case height:      { strcpy(dest,"height"); } break;
	case average:     { strcpy(dest,"average"); } break;
	case low: { strcpy(dest,"low"); } break;
	case very_low: { strcpy(dest,"very_low"); } break;


	default:
		{

		}
	}
}

bool CategoryReiting_e::from_cstr(const char* str)
{
	if( strncmp(str, "very_height", 16) == 0 )
	{
		value = very_height;
		return true;
	}

	if( strncmp(str, "height", 16) == 0 )
	{
		value = height;
		return true;
	}

	if( strncmp(str, "average", 16) == 0 )
	{
		value = average;
		return true;
	}

	if( strncmp(str, "low", 16) == 0 )
	{
		value = low;
		return true;
	}

	if( strncmp(str, "very_low", 16) == 0 )
	{
		value = very_low;
		return true;
	}
 
 
	//

	assert(false && " read from string error ");
	return false;
}

//======================================================================
//					Category							
//======================================================================
Category::Category(const WCHAR* filepath) throw(Error)
{
	if(  !ksfilefunc::fileExistsW(filepath)  )
	{
		String temp;
		temp += "Файл ";
		temp += ksstr::convertWstringToAstringWinapi(filepath);
		temp += " не найден!";
		throw Error(temp);
	}

	m_filepath = filepath;

	Load();
 
}

Category::~Category()
{
   assert(false);
}

static bool __Sort_class_Category(const std::string& a1, const std::string& a2)
{
	assert(false);  return false;

	if(a1 < a2)
	{
		return true;
	}

	return false;
}

void Category::Sort()
{
	assert(false);
}

bool Category::readKeyValue(std::string& key, std::string& value, const std::string& src)
{
 
	//bool  IniFile::parseKeyValueString(  std::string& s_OutKey, 
	//	std::string& s_OutValue,
	//	const std::string& src ) const 

	key = ""; 
	value = "";

	const size_t SLEN = src.length();
	if(SLEN == 0) return false;

	int nDivPos =  -1; // position '='

	// read m_key
	//
	for(size_t c=0; c<SLEN; c++)
	{
		if(  (src[c] == '\t') || (src[c] == ' ') || (src[c] == '\r') )
			continue;

		if( src[c] == '=' )
		{
			// found 
			nDivPos = (int)c;
			break;
		}


		key += src[c];
	}

	// read m_value
	//
	for(size_t c=nDivPos+1; c<SLEN; c++)
	{
		value += src[c];
	}

	// add code correct m_value .... 

//	assert(false && "   need check code ");
	return true;
}

void Category::Load() throw(Error)
{
 
   std::vector<std::string>  text;

   {
	   std::string str;
	   if(! ksstr::loadStrFromFileW(str, m_filepath.c_str()) )
	   {
		   String temp;
		   temp = "Ошибка загрузки из файла";
		   throw Error(temp);
	   }

	   ksstr::splitLines(text, str);
	   ksstr::trimStrings(text);
   }


    size_t count =0;

   // read category_data
   {
	  
	   while(true)
	   {
		   if( text[count].length() == 0 )
		   {
			   count++;
			   continue;
		   }

		   std::string key, value;


		   // read version_number
		   if(!readKeyValue(key, value, text[count] ))
		   {
			   throw Error("Ошибка чтения ключа");
		   }

		   if( key != "version_number" )
		   {
			throw Error("Ключ version_number не найден в файле категигории");
		   }

		   if( sscanf(value.c_str(), "%u", &m_category_data_s.version_number) != 1 )
		   {
				throw Error("Ошибка чтения значения version_number");
		   }

		   count++;

		   

		   // read CategoryReiting
		   if(!readKeyValue(key, value, text[count] ))
		   {
			   throw Error("Ошибка чтения ключа");
		   }

		   if( key != "CategoryReiting" )
		   {
			   throw Error("Ключ CategoryReiting не найден в файле категории");
		   }

		   m_category_data_s.reiting = value;
		   count++;


		   // read brief
		   if(!readKeyValue(key, value, text[count] ))
		   {
			   throw Error("Ошибка чтения ключа");
		   }

		   if( key != "brief" )
		   {
			   throw Error("Ключ brief не найден в файле категории");
		   }

		   m_category_data_s.brief = value;
		   count++;


		   break;
	   }

   }
   // end (read category_data)

   // read words
   while( count < text.size() )
   {
	   if(  text[count].length() == 0  )
	   {
		   count++;
		   continue;
	   }
	   
	   m_words.push_back( text[count] );
	   count++;
	   continue;



	   //break;
   }
   // end (read words)


}

void Category::Save() throw(Error)
{
	std::string text;

	// make category_data
	{
		text += "version_number=";
		char temp[32];
		sprintf(temp, "%u", m_category_data_s.version_number);
		text += temp;
		text += "\n";

		text += "CategoryReiting=";
		text += m_category_data_s.reiting;
		text += "\n";

		text += "brief=";
		text += m_category_data_s.brief;
		text += "\n";


	}
	// end (make category_data)

	// make word list
	{
		text += "\n\n\n";
		for(size_t c=0; c<m_words.size(); c++)
		{
			text += m_words[c];
			text += "\n";
		}
 

	}
	// end (make word list)

	
	if( !ksstr::saveStrToFileW(text, m_filepath.c_str()) )
	{
		String temp;
		temp += "Ошибка записи в файл ";
		temp += ksstr::convertWstringToAstringWinapi(m_filepath);

		throw Error(temp);
	}

 
}

size_t Category::GetNumWords() const
{
   return m_words.size();
}

bool Category::IsWordExists(const char* engWord) const
{
	std::string arg = engWord;
	for(size_t c=0; c<m_words.size(); c++)
	{
		if( arg == m_words[c] )
		{
			return true;
		}
	}

	return false;
}

std::string Category::GetWord(const size_t index) const
{
	return m_words[index];
}

bool Category::GetWord2(char* dest, int destsize, const size_t index) const
{
	if(index >= m_words.size())
	{
		return false;
	}

	std::string word = m_words[index];
	if(word.length()+1 > (size_t)destsize)
	{
		return  false;
	}

	strncpy(dest, word.c_str(), destsize);
	return true;
}

CategoryReiting_e  Category::GetCategoryReiting() const
{
	if( m_category_data_s.reiting == CategoryReiting_e::undefined )
	{
		String temp;
		temp.AssignF("недопустимое значение CategoryReiting .  FILE(%s)  LINE(%i)",  __FILE__, __LINE__);
		CoreHandleError(ERROR_FLAG_CRITICAL|ERROR_FLAG_SHOWMESSAGEBOX, -1, temp);
	}

	return m_category_data_s.reiting;
}

UINT Category::GetVersionNumber() const
{
	if( m_category_data_s.version_number == 0xffffffff )
	{
		String temp;
		temp.AssignF("недопустимое значение version_number .  FILE(%s)  LINE(%i)",  __FILE__, __LINE__);
		CoreHandleError(ERROR_FLAG_CRITICAL|ERROR_FLAG_SHOWMESSAGEBOX, -1, temp);
	}

	return m_category_data_s.version_number;
}

std::string Category::GetBrief() const
{
	if( m_category_data_s.brief == "" )
	{
		String temp;
		temp.AssignF("недопустимое значение brief .  FILE(%s)  LINE(%i)",  __FILE__, __LINE__);
		CoreHandleError(ERROR_FLAG_CRITICAL|ERROR_FLAG_SHOWMESSAGEBOX, -1, temp);
	}

	return m_category_data_s.brief;
}





static void  __cdecl  __FoundFile(const WCHAR* lpszFileName,  void* pUserData )
{
	std::vector<std::wstring>* files = (std::vector<std::wstring>*)pUserData;
	files->push_back(lpszFileName);
}

//======================================================================
//					CategoryList						
//======================================================================

CategoryList::CategoryList(const WCHAR* directory) throw (Error)
{
	m_vector.reset( new std::vector< Category* > ()  );

	// load all
	{

		// search files
		std::vector<std::wstring> files;
		std::wstring path = directory;
		path += L"*.txt";
		if( !ksfilefunc::searchFilesW( (WCHAR*)path.c_str(), __FoundFile, (void*)&files  )   )
		{
			throw Error("Не найдено ни одной категории");
		}


		// load categories
		for(size_t c=0; c<files.size(); c++)
		{
			Category* new_cat = NULL;

			try 
			{
				Category* new_cat = new Category( files[c].c_str() );
			}
			catch (Error e)
			{
				throw Error( e.what() );	
			}
			 
			m_vector->push_back( new_cat );
		}



	}
	// end (load all)
}

CategoryList::~CategoryList()
{
	
}


UINT CategoryList::GetSize() const
{
	return  (UINT)m_vector->size();
}

Category* CategoryList::GetCategory(const size_t index)
{
	Category* res = m_vector->at(index);
	return res;
}


const Category* CategoryList::GetCategory(const size_t index) const
{	
	Category* res = m_vector->at(index);
	return res;
}




